package com.googlecode.jvmpart.proc.jdbc;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.jvmpart.proc.JvmProcessException;

public abstract class RowProcessor extends ConnProcessor {
	private static final Log logger = LogFactory.getLog(SimpleRowProcessor.class);
	public void doProcess() throws JvmProcessException {
		PreparedStatement ps = null;
		ResultSet rs = null;
		long row = 0;
		long error = 0;
		try {			
			ps = getConn().prepareStatement(getQuerySql());
			preparedStatement(ps, getParams());
			rs = ps.executeQuery();
			while(rs.next()) {
				try {
					row++;
					rowProcess(rs, row);
				} catch(JvmProcessException e) {
					error++;
					if(whenError(rs, row, e)) break;
				} finally {
				}
			}
			allProcessed(row, error);
		} catch(Exception e) {
			logger.error(e, e);
			throw new JvmProcessException("root error", e);
		} finally {
			try {
				if(rs!=null) rs.close();
				if(ps!=null) ps.close();
			} catch(Exception e) {};
		}
	}
	public abstract void preparedStatement(PreparedStatement ps, Map<String, String> params)throws SQLException;
	public abstract String getQuerySql();
	public abstract void rowProcess(ResultSet rs, long row) throws JvmProcessException;
	public abstract void allProcessed(long processed, long error) throws JvmProcessException;
	/**
	 * @param rs current result set
	 * @param row current row number
	 * @return if true will break the whole processing,false will continue
	 */
	public abstract boolean whenError(ResultSet rs, long row, Throwable t);
}
